package org.stratusdb.funsql.execute;

import java.util.HashMap;
import java.util.Vector;

import org.stratusdb.Config;
import org.stratusdb.error.Error;
import org.stratusdb.types.AbstractSimpleType;
import org.stratusdb.types.SQLVarchar;
import org.stratusdb.types.TableType;

public class EquiSelection extends UnaryOperator {

	private static final long serialVersionUID = 6313732867112964227L;

	private TableType inputTable;
	private int inputCount;
	private HashMap<Integer, AbstractSimpleType> attList;
	private Vector<Integer> projAttr;
	
	public EquiSelection(AbstractOperator child, HashMap<Integer,AbstractSimpleType> attList, Vector<Integer> projAttr) {
		super(child);
		this.attList = attList;
		this.projAttr = projAttr;
	}
	

	public EquiSelection(StoreScan pgStoreScan, int i, SQLVarchar sqlVarchar) {
		super(pgStoreScan);
		throw new NullPointerException();
	}

	@Override
	public Error open() {
		this.lastError = this.child.open();

		if (this.lastError != Error.NO_ERROR) {
			return this.lastError;
		}

		this.inputTable = this.child.next();
		this.inputCount = 0;
		this.lastError = this.child.getLastError();
		return this.lastError;
	}

	@Override
	public TableType next() {
		TableType resultTable = new TableType();
		this.lastError = Error.NO_ERROR;

		while (resultTable.size() < Config.EXECUTE_MAX_FETCHSIZE
				&& this.inputTable != null) {
			boolean flag = true;
			for(Integer attr : this.attList.keySet()) {
				if (this.inputCount < this.inputTable.size()) {
					if(inputTable.getTuple(this.inputCount)==null) break;
					AbstractSimpleType selectValue = inputTable.getTuple(
							this.inputCount).getValue(attr);
					if(selectValue==null) break;
					if (!selectValue.equals(this.attList.get(attr))) {
						flag = false;
					}
					
					this.inputCount++;
				} else {
					this.inputTable = this.child.next();
					this.inputCount = 0;

					if (this.lastError != Error.NO_ERROR) {
						return null;
					}
				}				
			}
			if(flag) {
				resultTable.addTuple(inputTable.getTuple(this.inputCount));
			}

		}
		if (resultTable.size() == 0)
			return null;
		else
			return filter(resultTable,this.projAttr);
	}

	@Override
	public Error close() {
		this.inputTable = null;
		this.inputCount = 0;

		return this.child.close();
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer("EquiSelection : Selectionsattribute : ");
		for(Integer key : this.attList.keySet()) {
			sb.append(key + " = " + this.attList.get(key));
		}
		sb.append(" : Projectionsattribute : ");
		for(Integer i : this.projAttr) {
			sb.append(i + " ");
		}
		return sb.toString();
	}

}
